
import TimerEvent from './TimerEvent'

export default class Clock{  
    constructor(options) {
        this.now = Date.now();

        // 当前列表
        this._active = [];
        // 待添加
        this._pendingInsertion = [];
        // 待删除
        this._freeEventArr = [];

        this.paused = !options.autoStart;
    }

    start() {
        if (this.paused) {
            this.paused = false;
        }
    }

    stop() {
        if (!this.paused) {
            this.paused = true;
        }
    }

    addEvent(options) {
        var event;
        if (this._freeEventArr.length) {
            event = this._freeEventArr.pop();
            event.setInfo(options);
        } else {
            event = new TimerEvent(options);
        }
        this._pendingInsertion.push(event);
        return event;
    }

    delayedCall(delay, callback, callbackContext, args) {
        return this.addEvent({ delay, callback, callbackContext, args });
    }

    clearPendingEvents() {
        this._pendingInsertion.length = 0;
        return this;
    }

    removeAllEvents() {
        this._pendingRemoval = this._pendingRemoval.concat(this._active);
        return this;
    }

    update(time, delta) {
        this.now = time;
        if (this.paused) {
            return;
        }
        delta *= (1 / PIXI.settings.TARGET_FPMS);

        // 插入
        var insertCount = this._pendingInsertion.length;
        for (var i = 0; i < insertCount; i++) {
            this._active.push(this._pendingInsertion[i])
        }
        this._pendingInsertion.length = 0;

        var realLen = 0;
        const arr = this._active;
        for (var i = 0, len = arr.length; i < len; i++) {
            var curEvent = this.arr[i];
			var needDelete = curEvent.orphan;
			if (needDelete) {
				for (let j = i + 1; j < arr.length; j++) {
					let tempEvent = arr[j];
					if (!tempEvent.orphan) {
						var temp = arr[i];
						arr[i] = arr[j];
						arr[j] = temp;
						realLen++;
						break;
					}
				}
			} else {
				arr[realLen++] = curEvent;
            }

            var event = arr[i];
            if (event.paused || event.orphan) {
                continue;
            }

            event.elapsed += delta;
            if (event.elapsed >= event.delay) {
                var remainder = event.elapsed - event.delay;
                //  Limit it, in case it's checked in the callback
                event.elapsed = event.delay;
                
                //  Process the event
                if (!event.hasDispatched) {
                    if (event.callback) {
                        if (event.callbackContext || event.args) {
                            event.callback.apply(event.callbackContext, event.args);
                        } else {
                            event.callback();
                        }
                    }
                    event.emit("complete", args)
                    event.hasDispatched = true;
                    
                }

                if (event.repeatCount > 0) {
                    event.repeatCount--;
                    event.elapsed = remainder;
                    event.hasDispatched = false;
                } else {
                    event.orphan = true;
                }
            }
        }

        let count = realLen;
        while (len > count) {
            this._freeEventArr.push(this._active.pop());
            count++;
        }
        this._active.length = realLen;
    }

    shutdown() {
        for (let i = 0; i < this._pendingInsertion.length; i++) {
            this._pendingInsertion[i].destroy();
        }

        for (let i = 0; i < this._active.length; i++) {
            this._active[i].destroy();
        }

        for (let i = 0; i < this._freeEventArr.length; i++) {
            this._freeEventArr[i].destroy();
        }

        this._active.length = 0;
        this._pendingRemoval.length = 0;
        this._freeEventArr.length = 0;
    }

    destroy() {
        this.shutdown();
    }
}
